import { Dispatch, SetStateAction, createContext, useEffect, useState } from "react";
import { MemberType, FriendType } from "../components/Member";
import { io } from "socket.io-client";
import Login from "../pages/Auth/Login";
import authencation from "../plugins/authencation";
import { RoomType } from "../components/Room";
import { getApplies, getFriends, getRooms } from "../apis";
import { mergeFriendMessage, mergeRoomMessage } from "../plugins/message";
import { ApplyType } from "../components/Apply";

export type SetContextType = {
    member: MemberType | undefined;
    token: string | null;
};
export type MemberContextType = SetContextType & {
    setMember: Dispatch<SetStateAction<SetContextType>>;
    friends: FriendType[] | undefined;
    rooms: RoomType[] | undefined;
    setFriends: Dispatch<SetStateAction<FriendType[]>>;
    setRooms: Dispatch<SetStateAction<RoomType[]>>;
    applies: ApplyType[] | undefined;
    setApplies: Dispatch<SetStateAction<ApplyType[]>>;
};

export const MemberContext = createContext<MemberContextType>({
    member: undefined,
    token: null,
    friends: undefined,
    rooms: undefined,
    setMember: () => null,
    setFriends: () => null,
    setRooms: () => null,
    applies: undefined,
    setApplies: () => null,
});

function MemberProvider({children}: {
    children: React.ReactNode,
}) {
    const [{member, token}, setMember] = useState<SetContextType>(() => ({
        member: undefined,
        token: null,
        friends: undefined,
    }));
    const [friends, setFriends] = useState<FriendType[]>([]);
    const [rooms, setRooms] = useState<RoomType[]>([]);
    const [applies, setApplies] = useState<ApplyType[]>([]);

    useEffect(() => {
        authencation.logined().then(() => {
            console.log('member logined', authencation.getMember(), authencation.getToken());
            setMember({
                member: authencation.getMember(),
                token: authencation.getToken(),
            });
        }).catch(() => {});

        return () => {
            if(window?.socket) {
                window.socket.close();
            }
        }
    }, []);

    useEffect(() => {
        console.log('member change', member);
        if(!member) {
            if(typeof window?.socket !== 'undefined') {
                window.socket.close();
                window.socket = undefined;
            }
            return;
        }
        initailize();
        if(window?.socket) {
            return;
        }

        const handler = io(`ws://localhost:3001`, {
            query: {
                token,
            }
        });

        handler.on('message', (data) => {
            console.log('received message', member.id, data.senderId, data);
            // 群消息
            if(data.chatTypeId === 'room') {
                setRooms((rooms) => {
                    return mergeRoomMessage(data, rooms, member.id === data.senderId);
                });
            }
            // 私人消息
            if(data.chatTypeId === 'person') {
                setFriends((friends) => {
                    return mergeFriendMessage(data, friends, member.id === data.senderId);
                });
            }
        });

        handler.on('apply', (data) => {
            console.log('received apply', data);
            if(data?.senderId === member.id) {
                localStorage.setItem(`apply-${data.receiverId}`, data.status);
                return;
            }
            // 新增好友申请
            setApplies((applies) => {
                return [data, ...applies];
            });
        });

        handler.on('accept', (data) => {
            console.log('received accept', data);
            // 入群通知
            if(data.chatTypeId === 'room') {
                setRooms((rooms) => {
                    return (rooms || []).map(room => {
                        if(room.id === data.chatId) {
                            if((room.members || []).filter(item => item.id === data.senderId).length) {
                                return room;
                            }
                            room.members = [...(room.members || []), data.member];
                            return room;
                        }
                        return room;
                    });
                });
            }
            // 好友通知
            if(data.chatTypeId === 'person') {
                setFriends((friends) => {
                    if((friends || []).filter(item => item.id === data.senderId).length) {
                        return friends;
                    }
                    return [...(friends || []), data.friend];
                });
            }
            // 修改申请状态
            setApplies((applies) => {
                return (applies || []).map((apply) => {
                    if(apply.id === data.id) {
                        return {...apply, status: data.status};
                    }
                    return apply;
                });
            });
        });

        window.socket = handler;

    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [member]);

    const initailize = () => {
        // 获取朋友列表
        getFriends().then((response) => {
            const { friends } = response || {};
            setFriends(friends || []);
        }).catch(() => {});

        // 获取群列表
        getRooms().then((response) => {
            const { rooms } = response || {};
            setRooms(rooms || []);
        }).catch(() => {});

        // 获取添加好友申请列表
        getApplies().then((response) => {
            const { applies } = response || {};
            setApplies(applies || []);
        }).catch(() => {});
    }

    return <>
        <MemberContext.Provider value={{member, token, setMember, rooms, friends, setFriends, setRooms, applies, setApplies}}>
            {
                member
                    ? children
                    : <Login />
            }
        </MemberContext.Provider>
    </>;
}

export default MemberProvider;
